import 'package:app_core/app_core.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';

import '../common/base_model/base_model.dart';

///自定义的异常code
enum NetErrCode {
  connectionTimeout(1001, '连接超时'),
  receiveTimeout(1002, '接收超时'),
  badResponse(1003, '服务器错误'),
  networkError(1004, '网络错误'),
  parseError(1005, '数据解析错误'),
  invalidResponse(1006, '响应格式错误'),
  businessError(1007, '业务错误'),
  unknown(1008, '未知错误');

  const NetErrCode(this.code, this.message);
  final int code;
  final String message;
}

class ApiResponse<T> {
  /// 请求是否成功
  final bool success;

  /// 成功时的数据（如果传入了T和fromJson，data类型为T，否则为后台原始['data']字段值）
  final dynamic data;

  /// 消息描述
  final String? message;

  /// 状态码
  final int? code;

  /// 整个原始响应数据
  final dynamic raw;

  ApiResponse.success(this.data, {this.message, this.code, this.raw}) : success = true;
  ApiResponse.error(this.message, {this.code, this.raw}) : success = false, data = null;

  bool get isSuccess => success;
  bool get isError => !success;
  // T? get safeData => isSuccess ? data : null;
  // T get requireData {
  //   if (!isSuccess) throw Exception(message ?? '请求失败😂');
  //   return data as T;
  // }

  T? get safeData {
    if (!isSuccess) return null;
    if (data is T) return data as T;
    return null;
  }

  T get requireData {
    if (!isSuccess) throw Exception(message ?? '请求失败��');
    if (data is T) return data as T;
    throw Exception('数据类型不匹配，期望 $T，实际 ${data.runtimeType}');
  }

  /// 便捷工厂：从Dio响应构建
  factory ApiResponse.fromResponse(Response response, {T Function(Map<String, dynamic>)? fromJson, Function(int code, String? msg)? onErrorCode}) {
    final resultData = response.data;
    try {
      final code = _parseCode(resultData['code']);
      final msg = resultData['message']?.toString() ?? resultData['msg']?.toString();

      /// 处理正常业务
      if (code == 0) {
        final payload = resultData['data'];
        return _createSuccessResponse<T>(payload, msg, code, resultData, fromJson);
      }
      onErrorCode?.call(code, msg);
      return ApiResponse<T>.error(msg ?? '请求返回错误', code: code, raw: resultData);
    } catch (e) {
      final errorMsg = '数据解析错误: ${e.toString()}';
      onErrorCode?.call(NetErrCode.parseError.code, errorMsg);
      return ApiResponse<T>.error(errorMsg, code: NetErrCode.parseError.code, raw: resultData);
    }
  }

  static ApiResponse<T> _createSuccessResponse<T>(
    dynamic payload,
    String? message,
    int code,
    Map<String, dynamic> raw,
    T Function(Map<String, dynamic>)? fromJson,
  ) {
    if (fromJson == null) {
      return ApiResponse<T>.success(payload, message: message, code: code, raw: raw);
    }
    if (payload is List) {
      final list = payload.whereType<Map<String, dynamic>>().map((item) => fromJson(item)).toList();
      return ApiResponse<T>.success(list as T, message: message, code: code, raw: raw);
    } else if (payload is Map<String, dynamic>) {
      final obj = fromJson(payload);
      return ApiResponse<T>.success(obj, message: message, code: code, raw: raw);
    }
    return ApiResponse<T>.success(payload, message: message, code: code, raw: raw);
  }

  static int _parseCode(dynamic code) {
    if (code is int) return code;
    if (code is String) return int.tryParse(code) ?? -1;
    return -1;
  }

  /// 从错误创建响应
  factory ApiResponse.fromError(dynamic error, {Function(int code, String? msg)? onErrorCode}) {
    NetErrCode errorCode;
    String msg;

    if (error is DioException) {
      switch (error.type) {
        case DioExceptionType.connectionTimeout:
          errorCode = NetErrCode.connectionTimeout;
          msg = errorCode.message;
          break;
        case DioExceptionType.receiveTimeout:
          errorCode = NetErrCode.receiveTimeout;
          msg = errorCode.message;
          break;
        case DioExceptionType.badResponse:
          errorCode = NetErrCode.badResponse;
          msg = errorCode.message;
          break;
        default:
          errorCode = NetErrCode.networkError;
          msg = error.message ?? errorCode.message;
      }
    } else if (error is Exception) {
      errorCode = NetErrCode.parseError;
      msg = error.toString();
    } else {
      errorCode = NetErrCode.unknown;
      msg = error.toString();
    }

    onErrorCode?.call(errorCode.code, msg);
    return ApiResponse<T>.error(msg, code: errorCode.code, raw: error);
  }
}
